package cn.mw.cmdb.processor;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.mw.cmdb.entity.InstanceGroupByPathAndStatus;
import cn.mw.cmdb.entity.InstanceInfo;
import cn.mw.cmdb.entity.ModelGroupInfo;
import cn.mw.cmdb.entity.ModelInfo;
import cn.mw.cmdb.param.*;
import cn.mw.cmdb.service.impl.CmdbServiceManage;
import cn.mw.cmdb.service.impl.CustomModelServiceImpl;
import cn.mw.cmdb.service.impl.InstanceServiceImpl;
import cn.mw.cmdb.service.impl.ModelGroupServiceImpl;
import cn.mw.cmdb.util.AssetsTool;
import cn.mw.cmdb.util.CMDBTool;
import cn.mw.components.mongodb.entity.CriteriaOpsType;
import cn.mw.components.mongodb.entity.SubCondition;
import cn.mw.microMonitorCommon.api.cmdb.TreeView;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.SerializationUtils;

import java.util.*;
import java.util.stream.Collectors;

import static cn.mw.cmdb.util.ValConvertUtil.strValueConvert;

public class TreeProcessorFinanceModel implements TreeProccessorTable {

    private CmdbServiceManage cmdbServiceManage;

    private TableSearchParam tableSearchParam;

    public TreeProcessorFinanceModel(CmdbServiceManage cmdbServiceManage, TableSearchParam tableSearchParam) {
        this.cmdbServiceManage = cmdbServiceManage;
        this.tableSearchParam = tableSearchParam;
    }

    @Override
    public List genTreeData(TableDataProcessorContext context) throws Exception {
        List<TreeView> list = new ArrayList();

        InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        ModelGroupServiceImpl modelGroupService = (ModelGroupServiceImpl) cmdbServiceManage.getModelService(ModelGroupServiceImpl.ID);
        CustomModelServiceImpl customModelService = (CustomModelServiceImpl) cmdbServiceManage.getModelService(CustomModelServiceImpl.ID);

        // 查询所有金融元父模型
        ModelSearchParam parentModelSearchParam=new ModelSearchParam();
        parentModelSearchParam.addSubCondition(CMDBTool.getFieldName(ModelInfo::getFunctionModule), new SubCondition(CriteriaOpsType.in.name(), FunctionModuleEnum.financeReport.getCode()));
        List<ModelInfo> financeParentModelInfos = customModelService.getAllModelByParentGroup(parentModelSearchParam);
        Map<String, ModelInfo> modelId2FinanceParentModelInfoMap = financeParentModelInfos.stream().collect(Collectors.toMap(ModelInfo::getId, item -> item, (o1, o2) -> o1));
        List<String> financeParentModelIds = financeParentModelInfos.stream().map(ModelInfo::getId).toList();

        // 查询所有金融元父模型普通模型
        ModelSearchParam modelSearchParam = new ModelSearchParam();
        BeanUtil.copyProperties(context.getTableSearchParam(), modelSearchParam, CopyOptions.create().setIgnoreNullValue(true));
        modelSearchParam.addSubCondition(CMDBTool.getFieldName(ModelInfo::getParentModelIds), new SubCondition(CriteriaOpsType.elemMatch.name(), financeParentModelIds));
        List<ModelInfo> modelInfos = customModelService.doSelectShowNormalModelByPath(modelSearchParam);

        Set<String> modelIds = new HashSet<>();
        Set<String> groupSet = new HashSet<>();
        ModelInfo parentModelInfo;
        for (ModelInfo modelInfo:modelInfos) {
            modelIds.add(modelInfo.getId());
            groupSet.addAll(modelInfo.getGroupPath());

            // 普通模型替换成金融元父模型
            for (String parentModelId : modelInfo.getParentModelIds()) {
                if (modelId2FinanceParentModelInfoMap.get(parentModelId) != null) {
                    parentModelInfo = SerializationUtils.clone(modelId2FinanceParentModelInfoMap.get(parentModelId));
                    parentModelInfo.setGroupId(modelInfo.getGroupId());
                    parentModelInfo.setId(String.format("%s_%s", modelInfo.getGroupId(), parentModelInfo.getId()));
                    list.add(parentModelInfo);
                }
            }
        }

        InstanceSearchParam param = new InstanceSearchParam();
        BeanUtil.copyProperties(context.getTableSearchParam(), param, CopyOptions.create().setIgnoreNullValue(true));
        param.addSubCondition(CMDBTool.getFieldName(InstanceInfo::getFinanceParentId), new SubCondition(CriteriaOpsType.in.name(), financeParentModelIds));
        List<InstanceGroupByPathAndStatus> groupRet = instanceService.groupCountByPathAndStatus(param);
        for (InstanceGroupByPathAndStatus instanceGroupByPathAndStatus:groupRet) {
            if (instanceGroupByPathAndStatus.getFinanceParentId() != null && CollectionUtils.isNotEmpty(instanceGroupByPathAndStatus.getPath())) {
                instanceGroupByPathAndStatus.getPath().remove(instanceGroupByPathAndStatus.getPath().size() - 1);
                if (instanceGroupByPathAndStatus.getPath().size() > 0) {
                    instanceGroupByPathAndStatus.getPath().add(String.format("%s_%s", instanceGroupByPathAndStatus.getPath().get(instanceGroupByPathAndStatus.getPath().size() - 1)
                            , instanceGroupByPathAndStatus.getFinanceParentId()));
                } else {
                    instanceGroupByPathAndStatus.getPath().add(instanceGroupByPathAndStatus.getFinanceParentId());
                }
            }
        }
        Map<String, List<AssetsTool.ItemAssetsStatusContext>> idContextMap = AssetsTool.initModelAndGroupIdSet(new HashSet<>(), new HashSet<>(), groupRet);

        GroupSearchParam searchParam = new GroupSearchParam();
        searchParam.addSubCondition(CMDBTool.getFieldName(ModelGroupInfo::getId), new SubCondition(CriteriaOpsType.in.name(), new ArrayList<>(groupSet)));
        List<ModelGroupInfo> groupTree = modelGroupService.getShowModelGroupList(searchParam);
        if (null != groupTree) {
            list.addAll(groupTree);
        }

        for (TreeView treeView : list) {
            String id = strValueConvert(treeView.getId());
            List<AssetsTool.ItemAssetsStatusContext> contexts = idContextMap.get(id);
            if (contexts == null) {
                contexts = idContextMap.get(String.format("%s_%s", strValueConvert(treeView.getParentId()), id));
            }
            if (null != contexts) {
                treeView.setCount(AssetsTool.calcItemAssetsStatusCount(contexts));
            }
        }
        return list;
    }
}
